//
//  RxMoyaMapper.swift
//  Exam-iOS
//
//  Created by 李胜锋 on 2018/3/6.
//  Copyright © 2018年 李胜锋. All rights reserved.
//

import Foundation
import RxSwift
import ObjectMapper
import Moya
import XCGLogger

public enum LSFNetError: Error {
    ///Json解析错误
    case jsonError
    ///网络请求错误
    case requestFailed
    ///没有返回data
    case noResponse
    ///返回数据为空， code返回正确
    case nilData
    case tokenInvalid
    ///返回错误码
    case errorCode(code: Int, msg: String)
    
    func descript() -> String {
        var msg = ""
        switch self {
        case .jsonError:
            msg = "服务器数据解析错误"
        case .requestFailed:
            msg = "网络请求错误"
        case .noResponse:
            msg = "服务器错误，response为空"
        case .nilData:
            msg = "json解析错误"
        case .tokenInvalid:
            msg = "token失效"
        case .errorCode(let code, let message):
            msg = "\(code):" + message
        }
       
        return msg
    }
}

func showError(_ error: Error) {
    if error is LSFNetError {
        let err = error as! LSFNetError
        let msg = err.descript()
            
        lsf_alert(msg)
    }
    else {
        lsf_alert(error.localizedDescription)
    }
}

public enum RequestStatus: Int {
    case success = 0
    case error
}

fileprivate let k_RESULT_CODE = "code"
fileprivate let k_RESULT_MSG = "msg"
fileprivate let k_RESULT_DATA = "data"
fileprivate let k_TOKEN_INVALID_CODE = 1001
fileprivate let k_UID_ERROR = 1008001

public extension Observable {
    
  
    ///解析json
    public func mapRespnseJson() -> Observable<Any?> {
        
        return map { response in
            guard let data = try? self.responseData(response: response) else { return nil }
            return data
        }
    }
    
    ///解析对象
    public func mapRespnseToObject<T: BaseMappable>(type: T.Type) -> Observable<T> {

        return map { response in
            
            guard let json = try? self.responseData(response: response) else {
                throw LSFNetError.jsonError
            }
            
            guard let data = json as? [String: Any] else {
                throw LSFNetError.jsonError
            }
            
            let object = Mapper<T>().map(JSON: data)!
            return object
        }
    }
    
    ///解析数组
    func mapRespnseToObjectArray<T: BaseMappable>(type: T.Type) -> Observable<[T]> {
        return map { response in
            
            guard let json = try? self.responseData(response: response) else {
                throw LSFNetError.jsonError
            }
            
            guard let dataArray = json as? [Any] else {
                throw LSFNetError.jsonError
            }
            
            var objects = [T]()
            for object in dataArray {
                if let data = object as? [String: Any] {
                    let object = Mapper<T>().map(JSON: data)!
                    objects.append(object)
                }
            }
            return objects
        }
    }

    private func responseData(response: Any) throws -> Any? {
        
        guard let response = response as? Moya.Response else {
            throw LSFNetError.noResponse
        }
        //检查状态码
        guard ( (200...209) ~= response.statusCode) else {
            throw LSFNetError.requestFailed
        }
        
        guard let json = try? JSONSerialization.jsonObject(with: response.data, options: JSONSerialization.ReadingOptions(rawValue: 0)) as! [String: Any] else {
            throw LSFNetError.nilData
        }
        
        //服务器返回code
        guard let code = json[k_RESULT_CODE] as? Int else {
            throw LSFNetError.jsonError
        }
        
        XCGLogger.default.debug(json)
        //返回正确的code
        if code == RequestStatus.success.rawValue {
            let data = json[k_RESULT_DATA]
            return data
        }
            ///token失效、UID无效
        else if code == k_TOKEN_INVALID_CODE ||
            code == k_UID_ERROR ||
            code == 1108001 {
            AccountService.default.tokenInvalid()
            showLogin()
            throw LSFNetError.tokenInvalid
        }
        else {
            let msg = json[k_RESULT_MSG] as? String ?? "error nil"
            throw LSFNetError.errorCode(code: code, msg: msg)
        }
    }
}
